/*
 *-----------------------------------------------------------------------------
 * Copyright 2012 NCR Corporation
 *-----------------------------------------------------------------------------
 * All revision information is updated automatically from source code control
 * change records - please do not manually edit.
 *-----------------------------------------------------------------------------
 *
 *-----------------------------------------------------------------------------
 * $LastChangedRevision:: 4686                                      $
 * $LastChangedBy:: ma250087                                        $
 * $LastChangedDate:: 2012-05-18 15:14:49 -0400 (Fri, 18 May 2012)  $
 *-----------------------------------------------------------------------------
 */
package com.ncr.travel.airline.shared.configuration.checkin;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ncr.travel.tas.configuration.model.ConfigurationValue;
import com.ncr.travel.tas.configuration.service.messaging.ConfigurationService;
import com.ncr.travel.tas.configuration.service.messaging.ConfigurationValueCriteria;
import com.ncr.travel.tas.shared.configuration.ConfigurationKey;
import com.ncr.travel.tas.shared.configuration.ConfigurationNodeEnum;
import com.ncr.travel.tas.shared.configuration.ConfigurationProductKey;
import com.ncr.travel.tas.shared.configuration.ConfigurationServiceException;

/**
 * @author ms185252
 * @version $Revision: 4686 $
 * @since <a href="http://jira.sweng.ncr.com/browse/[current_issue_number]">[Project/effort name] Project</a>
 */
public abstract class CommonCheckInConfigurationImpl implements CommonCheckInConfiguration {

    private final static Logger logger = LoggerFactory.getLogger(CommonCheckInConfigurationImpl.class);

    /**
     * Cache of data retrieved from configuration. The cache key is derived from an instance of 
     * <code>ConfigurationValueCriteria</code>.
     */
    private static Map<String, ConfigurationValue> valueCache = new HashMap<String, ConfigurationValue>();

    private ConfigurationService configurationService;

    public ConfigurationService getConfigurationService() {
        return this.configurationService;
    }
    
    /**
     * Required implementation; clears local cache and pre-loads information as needed.
     *
     * @see CommonCheckInConfiguration#reset()
     */
    @Override
    public void reset() {
        CommonCheckInConfigurationImpl.valueCache.clear();
    }

    public void setConfigurationService(ConfigurationService configurationService) {
        this.configurationService = configurationService;
    }

    private ConfigurationValue getCachedValue(ConfigurationValueCriteria criteria) {
        return CommonCheckInConfigurationImpl.valueCache.get(criteria.getCompositeKey());
    }

    private void storeCachedValue(ConfigurationValueCriteria criteria, ConfigurationValue value) {
        CommonCheckInConfigurationImpl.valueCache.put(criteria.getCompositeKey(), value);
    }

    protected ConfigurationValue loadValueFromService(ConfigurationNodeEnum type, ConfigurationProductKey product,
            ConfigurationKey key) {
        logger.info("Loading configuration value for " + key + " in product " + product + "...");
        ConfigurationValueCriteria criteria = new ConfigurationValueCriteria(type, product, key);
        ConfigurationValue value = getCachedValue(criteria);
        if (null == value) {
            logger.info("Loading configuration data from database");
            List<ConfigurationValue> values = this.configurationService.findConfigurationValue(criteria);
            // verify value
            if (values.size() > 1) {
                logger.error("Multiple configuration values found. Unable to determine which one is correct.");
                throw new ConfigurationServiceException("Could not find a single value for: " + key, null);
            } else if (values.isEmpty()) {
                logger.error("No value found for: " + key);
                throw new ConfigurationServiceException("No value found for: " + key, null);
            }

            // else values.size() == 1
            value = values.get(0);
            storeCachedValue(criteria, value);
            logger.info("Loading Configuration (" + key + ") Value: " + value.getValue() + " (with "
                    + value.getChildValues().size() + " children)");
        }
        return value;
    }
    
}
